package com.sc.nft.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.MallMemberDao;
import com.sc.nft.dao.StaticDataDao;
import com.sc.nft.entity.MallMember;
import com.sc.nft.entity.MallMemberEquity;
import com.sc.nft.entity.UserInfo;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.EditAdminMallMemberVO;
import com.sc.nft.enums.MallMemberEquityTypeEnum;
import com.sc.nft.enums.MemberEquityTemplateeceiveCycleEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.*;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.Beans;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 商城会员 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-03-29
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class MallMemberServiceImpl implements MallMemberService {

    private final MallMemberDao mallMemberDao;
    @Autowired
    MallMemberEquityService mallMemberEquityService;
    @Autowired
    MallMemberEquityTemplateService mallMemberEquityTemplateService;
    private final UserCollectionService userCollectionService;
    private final StaticDataDao staticDataDao;
    private final MallMemberEquityUseRecordService mallMemberEquityUseRecordService;

    /**
     * 获取商城会员列表(管理后台)
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public Page<AdminMallMemberPageDTO> getAdminMallMemberPageDTO(Integer pageNo, Integer pageSize) {
        return mallMemberDao.getAdminMallMemberPageDTO(pageNo, pageSize);
    }

    /**
     * 获取商城会员列表(APP)
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public Page<MallMemberPageDTO> getMallMemberPageDTO(UserInfo user, Integer pageNo, Integer pageSize) {
        Date now = new Date();
        // 获取所有在使用的商城会员权益模版
        List<MallMemberEquityTemplate> mallMemberEquityTemplates = mallMemberEquityTemplateService.templatesAlreadyUsed();
        // 权益不叠加
        List<MallMemberEquityTemplate> nonOverlappingInterests = mallMemberEquityTemplates.stream().filter(mallMemberEquityTemplate -> !mallMemberEquityTemplate.getSuperpositionInterests()).collect(Collectors.toList());
        List<Long> nonOverlappingInterestIds = nonOverlappingInterests.stream().map(mallMemberEquityTemplate -> mallMemberEquityTemplate.getId()).collect(Collectors.toList());
        // 已经处理过的的不叠加权益模版 不在这里就可以享有 在这里就不能享有
        List<Long> disposeTemplateId = new ArrayList<>();

        Page<MallMemberPageDTO> mallMemberPageDTOPage = mallMemberDao.getMallMemberPageDTO(pageNo, pageSize);
        List<MallMemberPageDTO> records = mallMemberPageDTOPage.getRecords();
        // 查询出NONO商城ID
        String noNoDaoId = staticDataDao.getByType("noNo_dao_id").getValue();
        for (MallMemberPageDTO memberPageDTO : records) {
            memberPageDTO.setDaoId(Long.valueOf(noNoDaoId));
            List<UserCollection> userCollections = userCollectionService.getListByCollercitonId(user.getId(), memberPageDTO.getCollectionId());
            // 是否是会员
            Boolean isHold = !CollectionUtils.isEmpty(userCollections);
            // 领取周期
            MemberEquityTemplateeceiveCycleEnum receiveCycle = null;
            // 是否有优先购机会
            List<MallMemberEquityPageDTO> isPriorityList = new ArrayList<>();
            List<MallMemberEquityPageDTO> mallMemberEquityPageDTO = mallMemberEquityService.getMallMemberEquityPageDTO(memberPageDTO.getId());
            for (MallMemberEquityPageDTO memberEquityPageDTO : mallMemberEquityPageDTO) {
                if (isHold) {
                    if (nonOverlappingInterestIds.contains(memberEquityPageDTO.getMallMemberEquityTemplateId())) {
                        if (disposeTemplateId.contains(memberEquityPageDTO.getMallMemberEquityTemplateId())) {
                            // 说明这个权益已经处理过了
                            memberEquityPageDTO.setIsHold(Boolean.FALSE);
                        } else {
                            //  说明这个权益不叠加
                            memberEquityPageDTO.setIsHold(Boolean.TRUE);
                            disposeTemplateId.add(memberEquityPageDTO.getMallMemberEquityTemplateId());
                        }
                    } else {
                        // 说明这个权益叠加
                        memberEquityPageDTO.setIsHold(Boolean.TRUE);
                    }
                } else {
                    // 说明不是会员
                    memberEquityPageDTO.setIsHold(Boolean.FALSE);
                }
                if (MallMemberEquityTypeEnum.COMMODITY_PRIORITY == memberEquityPageDTO.getType()) {
                    // 优先购
                    receiveCycle = memberEquityPageDTO.getReceiveCycle();
                    if (memberEquityPageDTO.getIsHold()) {
                        isPriorityList.add(memberEquityPageDTO);
                    }
                }
            }
            memberPageDTO.setIsHold(isHold);
            memberPageDTO.setReceiveCycle(receiveCycle);
            memberPageDTO.setMallMemberEquityPageDTOList(mallMemberEquityPageDTO);
            // 判断是否还有优先购机会
            if (CollectionUtils.isEmpty(isPriorityList)) {
                memberPageDTO.setSurplusNum(0);
            } else {
                Integer surplusNum = 0;
                for (MallMemberEquityPageDTO memberEquityPageDTO : isPriorityList) {
                    Map<String, Date> timeMap = memberEquityPageDTO.getReceiveCycle().getTimeMap(now);
                    Date startTime = null;
                    Date endTime = null;
                    if (Objects.nonNull(timeMap)) {
                        startTime = timeMap.get("startTime");
                        endTime = timeMap.get("endTime");
                    }
                    // 查询用户是否使用过优先购机会
                    List<MallMemberEquityUseRecord> byMallMemberEquityId = mallMemberEquityUseRecordService.getByMallMemberEquityId(memberPageDTO.getId(), memberEquityPageDTO.getMallMemberEquityTemplateId(), user.getId(), startTime, endTime);
                    surplusNum = surplusNum + memberEquityPageDTO.getLimitCountPerUser() - byMallMemberEquityId.size();
                }
                if (surplusNum < 0){
                    surplusNum = 0;
                }
                memberPageDTO.setSurplusNum(surplusNum);
            }
        }

        // 根据排序字段排序
        List<MallMemberPageDTO> collect = records.stream().sorted(Comparator.comparing(MallMemberPageDTO::getSort).reversed())
                .collect(Collectors.toList());
        mallMemberPageDTOPage.setRecords(collect);
        return mallMemberPageDTOPage;
    }

    /**
     * 获取商城会员详情
     *
     * @param id
     * @return
     */
    @Override
    public AdminMallMemberDetailDTO getAdminMallMemberDetailDTO(Long id) {
        AdminMallMemberDetailDTO adminMallMemberDetailDTO = mallMemberDao.getAdminMallMemberDetailDTO(id);
        List<AdminMallMemberEquityDTO> adminMallMemberEquityDTOList = mallMemberEquityService.getAdminMallMemberEquityDTO(id);
        adminMallMemberDetailDTO.setAdminMallMemberEquityDTOList(adminMallMemberEquityDTOList);
        return adminMallMemberDetailDTO;
    }

    /**
     * 添加或者编辑商城会员
     *
     * @param editAdminMallMemberVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editMallMember(EditAdminMallMemberVO editAdminMallMemberVO) {
        MallMember member = mallMemberDao.getByMemberLv(editAdminMallMemberVO.getMemberLv(), editAdminMallMemberVO.getId());
        Assert.isNull(member, () -> new GlobalRunTimeException("已存在该会员等级的会员"));

        if (Objects.nonNull(editAdminMallMemberVO.getId())) {
            // 编辑
            MallMember mallMemberInDb = getById(editAdminMallMemberVO.getId());
            Assert.notNull(mallMemberInDb, () -> new GlobalRunTimeException("商城会员不存在"));
            Assert.isFalse(mallMemberInDb.getStatus(), () -> new GlobalRunTimeException("商城会员已启用，不可编辑"));
            Beans.copyProperties(editAdminMallMemberVO, mallMemberInDb);
            mallMemberDao.updateById(mallMemberInDb);
            // 编辑会员权益
            mallMemberEquityService.update(mallMemberInDb.getId(), editAdminMallMemberVO.getMallMemberEquityVOList());
        } else {
            // 添加
            MallMember mallMember = new MallMember();
            mallMember.setStatus(Boolean.FALSE);
            Beans.copyProperties(editAdminMallMemberVO, mallMember);
            mallMember.insert();
            // 添加会员权益
            mallMemberEquityService.update(mallMember.getId(), editAdminMallMemberVO.getMallMemberEquityVOList());
        }
    }

    /**
     * 商城会员启用
     *
     * @param id
     */
    @Override
    public void enable(Long id) {
        MallMember mallMember = getById(id);
        Assert.notNull(mallMember, () -> new GlobalRunTimeException("商城会员不存在"));
        mallMemberDao.updateStatus(id, Boolean.TRUE);
    }

    /**
     * 商城会员禁用
     *
     * @param id
     */
    @Override
    public void disable(Long id) {
        MallMember mallMember = getById(id);
        Assert.notNull(mallMember, () -> new GlobalRunTimeException("商城会员不存在"));
        mallMemberDao.updateStatus(id, Boolean.FALSE);
    }

    /**
     * 修改商城会员排序
     *
     * @param id
     * @param sort
     */
    @Override
    public void updateSort(Long id, Integer sort) {
        MallMember mallMember = getById(id);
        Assert.notNull(mallMember, () -> new GlobalRunTimeException("商城会员不存在"));
        mallMemberDao.updateSort(id, sort);
    }

    /**
     * 根据id获取商城会员
     *
     * @param id
     * @return
     */
    @Override
    public MallMember getById(Long id) {
        return mallMemberDao.getById(id);
    }

    /**
     * 获取用户商城会员
     *
     * @param user
     * @return
     */
    @Override
    public List<UserMallMemberDTO> getUserMallMember(UserInfo user) {
        return mallMemberDao.getUserMallMember(user.getId());
    }

    /**
     * 获取商城会员列表(用户)
     *
     * @return
     */
    @Override
    public List<UserMallMemberDTO> getUserMallMemberPageDTO(UserInfo user) {
        // 获取所有在使用的商城会员权益模版
        List<MallMemberEquityTemplate> mallMemberEquityTemplates = mallMemberEquityTemplateService.templatesAlreadyUsed();
        // 权益不叠加
        List<MallMemberEquityTemplate> nonOverlappingInterests = mallMemberEquityTemplates.stream().filter(mallMemberEquityTemplate -> !mallMemberEquityTemplate.getSuperpositionInterests()).collect(Collectors.toList());
        List<Long> nonOverlappingInterestIds = nonOverlappingInterests.stream().map(mallMemberEquityTemplate -> mallMemberEquityTemplate.getId()).collect(Collectors.toList());
        // 已经处理过的的不叠加权益模版 不在这里就可以享有 在这里就不能享有
        List<Long> disposeTemplateId = new ArrayList<>();

        List<UserMallMemberDTO> userMallMemberDTOList = getUserMallMember(user);

        for (UserMallMemberDTO userMallMemberDTO : userMallMemberDTOList) {
            List<MallMemberEquityPageDTO> mallMemberEquityPageDTO = mallMemberEquityService.getMallMemberEquityPageDTO(userMallMemberDTO.getId());
            for (MallMemberEquityPageDTO memberEquityPageDTO : mallMemberEquityPageDTO) {
                if (nonOverlappingInterestIds.contains(memberEquityPageDTO.getMallMemberEquityTemplateId())) {
                    if (disposeTemplateId.contains(memberEquityPageDTO.getMallMemberEquityTemplateId())) {
                        // 说明这个权益已经处理过了
                        memberEquityPageDTO.setIsHold(Boolean.FALSE);
                    } else {
                        //  说明这个权益不叠加
                        memberEquityPageDTO.setIsHold(Boolean.TRUE);
                        disposeTemplateId.add(memberEquityPageDTO.getMallMemberEquityTemplateId());
                    }
                } else {
                    // 说明这个权益叠加
                    memberEquityPageDTO.setIsHold(Boolean.TRUE);
                }
            }
            userMallMemberDTO.setMallMemberEquityPageDTOList(mallMemberEquityPageDTO);
        }
        return userMallMemberDTOList;
    }
}
